package login

import (
	"sync"

	kactor "kiwi/actor"
	kadefine "kiwi/actor/define"
	kahttpsvr "kiwi/actor/net/http/server"
	katimer "kiwi/actor/timer"
	kawork "kiwi/actor/work"
	kdebug "kiwi/debug"
	klog "kiwi/log"
	kservice "kiwi/service"
)

type globalConfig struct {
	TokenKey            string // 登录token key
	TokenExpireSec      int64  // 登录token超时秒数
	LoginMinIntervalSec int64  // 登录最小间隔秒数
	UseTLS              bool   // 是否启用TLS
	TLSCertFile         string // CertFile路径
	TLSKeyFile          string // KeyFile路径
}

type config struct {
	ListenAddr string // 监听地址
	WanAddr    string // 外网地址
}

type service struct {
	startedOnce  sync.Once
	startedWg    sync.WaitGroup
	stoppingOnce sync.Once
	stoppedOnce  sync.Once
	stoppedWg    sync.WaitGroup

	logger klog.ILogger

	pid *kadefine.PID

	timerMgr *katimer.Manager

	httpServer *kahttpsvr.Server
}

func Create(args ...any) kservice.IService {
	return &service{}
}

func (s *service) Start(ctx kadefine.Context, args ...any) error {
	return nil
}

func (s *service) Stop() {
	kactor.Poison(s.pid)
}

func (s *service) Receive(ctx kadefine.Context) {
	switch msg := ctx.Message().(type) {
	case *kawork.MessagePostWork:
		msg.Work.Execute(ctx)
		kawork.DestroyMessagePostWork(msg)

	case *kawork.MessageDispatchWork:
		msg.Err = msg.Work.Execute(ctx)
		ctx.Respond(msg)

	case *katimer.MessageTimeout:
		defer katimer.DestroyMessageTimeout(msg)

		err := s.timerMgr.Trigger(ctx, msg.ID)
		if err != nil {
			s.logger.Errorf("[%s] trigger timer fail, id=%d, tag=%d, %s", s.pid.Id, msg.ID, msg.Tag, err)
			return
		}

	case *kadefine.Started:
		s.startedOnce.Do(func() {
			defer func() {
				if p := recover(); p != nil {
					kdebug.WriteStackTraceFile(p, "")
					ctx.Stop(ctx.Self())
				}

				s.stoppedWg.Add(1)

				s.startedWg.Done()
			}()

			s.pid = ctx.Self()

			s.timerMgr = katimer.CreateManager(ctx)
		})

	case *kadefine.Stopping:
		s.stoppingOnce.Do(func() {
			defer func() {
				if p := recover(); p != nil {
					kdebug.WriteStackTraceFile(p, "")
				}
			}()
		})

	case *kadefine.Stopped:
		defer func() {
			if p := recover(); p != nil {
				kdebug.WriteStackTraceFile(p, "")
			}

			if s.timerMgr != nil {
				s.timerMgr.StopAll()
				s.timerMgr = nil
			}

			s.stoppedWg.Done()
		}()
	}
}
